package com.cheng.chengliving.commodity.service.impl;

import com.cheng.chengliving.commodity.vo.Catalog2Vo;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cheng.common.utils.PageUtils;
import com.cheng.common.utils.Query;

import com.cheng.chengliving.commodity.dao.CategoryDao;
import com.cheng.chengliving.commodity.entity.CategoryEntity;
import com.cheng.chengliving.commodity.service.CategoryService;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<CategoryEntity> listWithTree() {
        List<CategoryEntity> categoryEntities = baseMapper.selectList(null);

        //查出所有的一级分类
        List<CategoryEntity> treeMenus = categoryEntities.stream().filter(categoryEntity -> {
            return categoryEntity.getCatLevel() == 1;
        }).map(menu->{
            //递归找一级菜单的孩子，孩子会再找孩子。。。
             menu.setChildrenCategories(getChildren(menu, categoryEntities));
             return menu;
        }).sorted((category1,category2)->{
            return (category1.getSort() == null ? 0:category1.getSort()) - (category2.getSort() == null ? 0:category2.getSort());
        }).collect(Collectors.toList());
        return treeMenus;
    }


    //返回menu的子菜单集合[递归，子菜单可能还有子菜单]
    private List<CategoryEntity> getChildren(CategoryEntity rootMenu,List<CategoryEntity> allMenus){
        List<CategoryEntity> childrenList = allMenus.stream().filter(categoryEntity -> {
            return rootMenu.getId().equals(categoryEntity.getParentId());
        }).map(categoryEntity -> {
            categoryEntity.setChildrenCategories(getChildren(categoryEntity, allMenus));
            return categoryEntity;
        }).sorted((category1,category2)->{
            return (category1.getSort() == null ? 0:category1.getSort()) - (category2.getSort() == null ? 0:category2.getSort());
        }).collect(Collectors.toList());
        return childrenList;
    }

    /**
     * 1.该方法返回cascadeCategoryId,数据形式是[1,101,1001]
     * 2.递归查找parentId
     * @param categoryId
     * @return
     */
    @Override
    public Long[] getCascadeCategoryId(Long categoryId) {

        //1.先创建一个集合,把层级关系收集到集合中
        List<Long> cascadeCategoryId = new ArrayList<>();

        //2.调用方法进行处理-递归方法
        //cascadeCategoryId是引用传递,所以方法处理结束以后集合中已经收集到了所需的数据
        //返回的数据形如[1001,101,1]
        getParentCategoryId(categoryId, cascadeCategoryId);

        //3.将cascadeCategoryId集合进行反转[1001,101,1]=>[1,101,1001]
        //项目的逻辑+Java基础
        Collections.reverse(cascadeCategoryId);
        return cascadeCategoryId.toArray(new Long[cascadeCategoryId.size()]);
    }

    //返回当前所有的一级分类
    @Override
    public List<CategoryEntity> getLevel1Categories() {

        QueryWrapper<CategoryEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",0);
        List<CategoryEntity> categoryEntities =
                this.baseMapper.selectList(queryWrapper);
        return categoryEntities;
    }

    /**
     * @param selectList 就是所有的分类数据
     * @param parentCId  根据父级的分类Id,返回对应的分类数据
     * @return
     */
    private List<CategoryEntity> getParent_cid
    (List<CategoryEntity> selectList, Long parentCId) {

        //流式计算-filter
        List<CategoryEntity> categoryEntities = selectList.stream().filter(item -> {
            return item.getParentId().equals(parentCId);
        }).collect(Collectors.toList());
        return categoryEntities;
    }


    /**
     * 返回二级分类(包含三级分类)的数据-按照规定的格式Map<String, List<Catalog2Vo>>
     * 这里我们会使用到流式计算的 集合->map
     * 有一定难度-有层级关系
     * 老师分析: 我们需要一个辅助方法, 就是通过parentId获取对应的下一级的分类数据
     *
     * @return
     */
    @Override
    public Map<String, List<Catalog2Vo>> getCatalogJson() {

        //-先得到所有的分类数据[到数据表查一次]-> 在程序中进行业务处理 -> Map<String, List<Catalog2Vo>>

        //- 得到所有的分类数据[到数据表查一次]
        List<CategoryEntity> selectList =
                this.baseMapper.selectList(null);

        //- 从一级分类开始 -》 二级分类 -》 三级分类 ->

        //- 得到所有的一级分类
        List<CategoryEntity> level1Categories =
                getParent_cid(selectList, 0L);

        //- 遍历一级分类 ---> 最终得到 --》 Map<String, List<Catalog2Vo>>
        //- > 直接使用前面老师讲解的 Collectors.toMap

        Map<String, List<Catalog2Vo>> categoryMap =
                level1Categories.stream().collect(
                        Collectors.toMap(k -> {
                            return k.getId().toString();
                        }, v -> {
                            //这里就需要业务处理 List<Catalog2Vo>
                            List<Catalog2Vo> catalog2Vos = new ArrayList<>();

                            //-得到当前一级分类对应的所有二级分类
                            List<CategoryEntity> level2Categories =
                                    getParent_cid(selectList, v.getId());

                            //-遍历二级分类 - 使用流式计算
                            if (level2Categories != null && level2Categories.size() > 0) {
                                catalog2Vos = level2Categories.stream().map(l2 -> {

                                    //构建Catalog2Vo
                                    Catalog2Vo catalog2Vo =
                                            new Catalog2Vo(v.getId().toString(), null, l2.getId().toString(), l2.getName());

                                    //遍历l2对应的三级分类
                                    List<CategoryEntity> level3Categories = getParent_cid(selectList, l2.getId());
                                    if (level3Categories != null && level3Categories.size() > 0) {
                                        List<Catalog2Vo.Category3Vo> category3Vos = level3Categories.stream().map(l3 -> {
                                            //构建当前二级分类对应的三级分类对象
                                            Catalog2Vo.Category3Vo category3Vo =
                                                    new Catalog2Vo.Category3Vo(l2.getId().toString(), l3.getId().toString(), l3.getName());
                                            return category3Vo;
                                        }).collect(Collectors.toList());
                                        catalog2Vo.setCatalog3List(category3Vos);
                                    }
                                    return catalog2Vo;
                                }).collect(Collectors.toList());
                            }

                            return catalog2Vos;
                        }));

        return categoryMap;
    }

    /**
     * 编写方法,根据categoryId递归的查找层级关系
     * 比如接收到了categoryId=1001->parentId=101->parentId=1..直到parentId=0
     * cascadeCategoryId => 1001
     */

    private List<Long> getParentCategoryId(Long categoryId,List<Long> cascadeCategoryId) {

        //1.先把categoryId放入到集合中
        cascadeCategoryId.add(categoryId);
        //2.根据categoryId得到他的CategoryEntity
        CategoryEntity categoryEntity = this.getById(categoryId);
        //3.判断categoryEntity.parentId是否为0,如果不为0,说明他还有上级分类
        //1001
        //此处0应该为0L,否则!后面的表达式恒等于false
        if (!categoryEntity.getParentId().equals(0L)){
            //101,1...不断递归
            getParentCategoryId(categoryEntity.getParentId(),cascadeCategoryId);
        }
        return cascadeCategoryId;
    }

}
